#include "EWAUIWidget.hpp"

#include <limits.h>

namespace Eyer
{
    int EWAUIWidget::OnDraw()
    {
        return 0;
    }

    int EWAUIWidget::PrintInfo(int level)
    {
        EyerString tab = "";
        for(int i=0;i<level;i++){
            tab += "\t";
        }
        EyerLog("%sWidget Name: %s\n", tab.c_str(), widgetName.c_str());
        EyerLog("%s\tmode: %s, %s\n", tab.c_str(), widthMode.GetName().c_str(), heightMode.GetName().c_str());
        EyerLog("%s\tpos: %d, %d\n", tab.c_str(), xy.x(), xy.y());
#ifdef EYER_EWAUI_DEBUG
        EyerLog("%s\tinput: %d, %d\n", tab.c_str(), debug_suggestWidth, debug_suggestHeight);
#endif
        EyerLog("%s\tsize: %d, %d\n", tab.c_str(), wh.x(), wh.y());
        if(layoutType == EWAUILayoutType::LinearLayoutVertical_INVERT){
            EyerLog("%s\tLayourType: LinearLayoutVertical_INVERT\n", tab.c_str());
        }
        if(layoutType == EWAUILayoutType::LinearLayoutVertical){
            EyerLog("%s\tLayourType: LinearLayoutVertical\n", tab.c_str());
        }
        if(layoutType == EWAUILayoutType::LinearLayoutHorizontal){
            EyerLog("%s\tLayourType: LinearLayoutHorizontal\n", tab.c_str());
        }

        for(int i = 0; i < childWidget.size(); i++) {
            const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
            child->PrintInfo(level + 1);
        }

        return 0;
    }

    Vec2I EWAUIWidget::OnMeasure(int suggestWidth, int suggestHeight, int level)
    {
#ifdef EYER_EWAUI_DEBUG
        debug_suggestWidth = suggestWidth;
        debug_suggestHeight = suggestHeight;
#endif
        if(widthMode == LP::FIXED){
            suggestWidth = minWH.w();
        }
        if(heightMode == LP::FIXED){
            suggestHeight = minWH.h();
        }

        if(suggestWidth <= 0){
            suggestWidth = 0;
        }
        if(suggestHeight <= 0){
            suggestHeight = 0;
        }

        // 查看是否有子对象
        if(childWidget.size() <= 0){
            // childBoxSize = minWH;
            //没有子对象
            if (widthMode == LP::MATCH_PARENT) {
                if (suggestWidth == INT_MAX) {
                    wh.width(minWH.width());
                }
                else {
                    wh.width(suggestWidth);
                }
            }
            else if (widthMode == LP::WRAP_CONTENT) {
                wh.width(minWH.width());
            }
            else if (widthMode == LP::FIXED){
                wh.width(minWH.width());
            }

            if (heightMode == LP::MATCH_PARENT) {
                if(suggestHeight == INT_MAX){
                    int height = minWH.height();
                    wh.height(height);
                }
                else {
                    wh.height(suggestHeight);
                }
            }
            else if (heightMode == LP::WRAP_CONTENT) {
                wh.height(minWH.height());
            }
            else if (heightMode == LP::FIXED) {
                wh.height(minWH.height());
            }
        }

        else {
            // 计算子对象的大小
            Vec2I childBoxSize;

            if (layoutType == EWAUILayoutType::LinearLayoutHorizontal) {
                int offsetX = 0;
                int offsetY = 0;
                for(int i = 0; i < childWidget.size(); i++) {
                    const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
                    Vec2I childSize = child->OnMeasure(suggestWidth - offsetX, suggestHeight - offsetY, level + 1);
                    // 计算坐标
                    child->xy.x(offsetX);
                    child->xy.y(offsetY);

                    childBoxSize.height(std::max(childBoxSize.height(), childSize.height()));

                    offsetX += childSize.width();
                }
                // 重新计算 match parent 的子 Widget 的高度
                for(int i = 0; i < childWidget.size(); i++) {
                    const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
                    if(child->heightMode == LP::MATCH_PARENT){
                        child->wh.height(childBoxSize.height());
                    }
                }
                childBoxSize.width(offsetX);
            }
            else if (layoutType == EWAUILayoutType::LinearLayoutVertical) {
                int offsetX = 0;
                int offsetY = 0;
                for(int i = 0; i < childWidget.size(); i++) {
                    const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
                    Vec2I childSize = child->OnMeasure(suggestWidth - offsetX, suggestHeight - offsetY, level + 1);

                    // 计算坐标
                    child->xy.x(offsetX + child->marginLeft);
                    child->xy.y(offsetY + child->marginTop);

                    childBoxSize.width(std::max(childBoxSize.width(), childSize.width()));

                    offsetY += childSize.height();
                    offsetY += child->marginTop;
                    offsetY += child->marginBottom;
                }
                childBoxSize.height(offsetY);
            }
            else if (layoutType == EWAUILayoutType::LinearLayoutVertical_INVERT) {
                int offsetX = 0;
                int offsetY = 0;
                // for(int i = 0; i < childWidget.size(); i++) {
                for(int i = childWidget.size() - 1; i >= 0; i--){
                    const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
                    Vec2I childSize = child->OnMeasure(suggestWidth - offsetX, suggestHeight - offsetY, level + 1);

                    // 计算坐标
                    child->xy.x(offsetX + child->marginLeft);
                    child->xy.y(offsetY + child->marginTop);

                    childBoxSize.width(std::max(childBoxSize.width(), childSize.width()));

                    offsetY += childSize.height();
                    offsetY += child->marginTop;
                    offsetY += child->marginBottom;
                }
                // childBoxSize.height(offsetY);

                int marginTop = 0;
                if(suggestHeight != INT_MAX){
                    marginTop = suggestHeight - offsetY;
                    if(marginTop <= 0){
                        marginTop = 0;
                    }
                    for(int i = 0; i < childWidget.size(); i++) {
                        const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
                        child->xy.y(child->xy.y() + marginTop);
                    }
                    if(childWidget.size() > 0){
                        childWidget[childWidget.size() - 1]->marginTop = marginTop;
                    }
                }
                childBoxSize.height(offsetY + marginTop);
            }
            else if (layoutType == EWAUILayoutType::RetativeLayout) {
                int maxEndX = 0;
                int maxEndY = 0;
                for(int i = 0; i < childWidget.size(); i++) {
                    const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
                    Vec2I childSize = child->OnMeasure(suggestWidth, suggestHeight, level + 1);

                    if(widthMode == EWAUILayoutParams::MATCH_PARENT){
                        if(child->alignParentRight){
                            child->xy.x(suggestWidth - childSize.width());
                        }
                    }

                    maxEndX = std::max(maxEndX, child->xy.x() + childSize.width());
                    maxEndY = std::max(maxEndY, child->xy.y() + childSize.height());
                }
                childBoxSize.width(maxEndX);
                childBoxSize.height(maxEndY);
            }
            else if (layoutType == EWAUILayoutType::FixedLayout) {
                int maxEndX = 0;
                int maxEndY = 0;
                for(int i = 0; i < childWidget.size(); i++) {
                    const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
                    Vec2I childSize = child->OnMeasure(suggestWidth, suggestHeight, level + 1);

                    if(widthMode == EWAUILayoutParams::MATCH_PARENT){
                        if(child->alignParentRight){
                            child->xy.x(suggestWidth - childSize.width());
                        }
                    }

                    maxEndX = std::max(maxEndX, child->xy.x() + childSize.width());
                    maxEndY = std::max(maxEndY, child->xy.y() + childSize.height());
                }

                childBoxSize.width(maxEndX);
                childBoxSize.height(maxEndY);

                childBoxSize = minWH;
            }

            if (widthMode == LP::MATCH_PARENT) {
                if (suggestWidth == INT_MAX) {
                    wh.width(childBoxSize.width());
                }
                else {
                    wh.width(suggestWidth);
                }
            }
            else if (widthMode == LP::WRAP_CONTENT) {
                wh.width(childBoxSize.width());
            }
            else if (widthMode == LP::FIXED) {
                wh.width(minWH.width());
            }

            if (heightMode == LP::MATCH_PARENT) {
                if(suggestHeight == INT_MAX){
                    wh.height(childBoxSize.height());
                }
                else {
                    wh.height(suggestHeight);
                }
            }
            else if (heightMode == LP::WRAP_CONTENT) {
                wh.height(childBoxSize.height());
            }
            else if (heightMode == LP::FIXED) {
                wh.height(minWH.height());
            }
        }

        return wh;
    }

    int EWAUIWidget::GetMinWidth()
    {
        return minWH.x();
    }

    int EWAUIWidget::GetMinHeight()
    {
        return minWH.y();
    }

    int EWAUIWidget::SetMinWidth(int minWidth)
    {
        minWH.x(minWidth);
        return 0;
    }

    int EWAUIWidget::SetMinHeight(int minHeight)
    {
        minWH.y(minHeight);
        return 0;
    }

    int EWAUIWidget::SetChildCustomXY(const Vec2I & _customXY)
    {
        customXY = _customXY;
        for(int i = 0; i < childWidget.size(); i++) {
            const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
            child->customXY = _customXY;
        }
        return 0;
    }

    EWAUIWidget::EWAUIWidget(EWAUILayoutParams _width, EWAUILayoutParams _height)
        : minWH(0, 0)
        , offsetXY(0, 0)
    {
        widthMode = _width;
        heightMode = _height;
    }

    EWAUIWidget::~EWAUIWidget()
    {

    }

    int EWAUIWidget::AddWidget(const EyerSmartPtr<EWAUIWidget> & widget)
    {
        childWidget.push_back(widget);
        return 0;
    }

    int EWAUIWidget::RemoveAllWidget()
    {
        childWidget.clear();
        return 0;
    }

    int EWAUIWidget::SetWidgetName(const EyerString & _widgetName)
    {
        widgetName = _widgetName;
        return 0;
    }

    int EWAUIWidget::Draw(int level)
    {
        std::vector<EyerSmartPtr<EWAUIGraph>> tempGraphList;
        // 绘制子 Widget
        for(int i = 0; i < childWidget.size(); i++){
            const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
            // 绘制子内容
            child->Draw(level + 1);
            for(int i=0;i<child->GetUIGraphSize();i++){
                EyerSmartPtr<EWAUIGraph> g = child->GetUIGraph(i);
                // 重新计算位置, 转化为父对象的坐标系
                g->Transform(child->xy + offsetXY, wh);
                // g->Transform(child->xy, wh);
                if(g->IsValid()){
                    tempGraphList.push_back(g);
                }
            }
        }
        // 绘制本 Widget
        RemoveAllUIGraph();

        OnDraw();

        for(int i = 0; i < tempGraphList.size(); i++){
            graphList.push_back(tempGraphList[i]);
        }

        return 0;
    }

    int EWAUIWidget::RemoveAllUIGraph()
    {
        graphList.clear();
        return 0;
    }

    int EWAUIWidget::AddUIGraph(const EyerSmartPtr<EWAUIGraph> & graph)
    {
        graphList.push_back(graph);
        return 0;
    }

    int EWAUIWidget::GetUIGraphSize()
    {
        return graphList.size();
    }

    int EWAUIWidget::SetLayoutType(EWAUILayoutType _layoutType)
    {
        layoutType = _layoutType;
        return 0;
    }

    EyerSmartPtr<EWAUIGraph> EWAUIWidget::GetUIGraph(int index)
    {
        EyerSmartPtr<EWAUIGraph> graph = graphList[index];
        return graph;
    }

    bool EWAUIWidget::IsDraging()
    {
        return isDrag;
    }

    int EWAUIWidget::SetMinWH(int w, int h)
    {
        minWH.width(w);
        minWH.height(h);
        return 0;
    }

    int EWAUIWidget::SetBGColor(const EyerColor & _bgColor)
    {
        bgColor = _bgColor;
        return 0;
    }

    bool EWAUIWidget::MousePressEvent     (const Vec2I & pos)
    {
        mouseStatus = EWAUIMouseStatus::PRESSED;
        isDrag = true;
        pressPos = pos;
        bool ret = OnMousePressEvent(pos);
        if(ret){
            // 向下传递
            for(int i = 0; i < childWidget.size(); i++) {
                const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
                Vec2I transPos = pos - (child->xy + offsetXY);
                if(transPos.x() < 0){
                    continue;
                }
                if(transPos.y() < 0){
                    continue;
                }
                if(transPos.x() > child->wh.x()){
                    continue;
                }
                if(transPos.y() > child->wh.y()){
                    continue;
                }

                child->MousePressEvent(transPos);
            }
        }
        return ret;
    }

    bool EWAUIWidget::MouseReleaseEvent   (const Vec2I & pos)
    {
        isDrag = false;
        mouseStatus = EWAUIMouseStatus::STAND_BY;
        bool ret = OnMouseReleaseEvent(pos);
        if(ret){
            // 向下传递
            for(int i = 0; i < childWidget.size(); i++) {
                const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
                Vec2I transPos = pos - (child->xy + offsetXY);
                child->MouseReleaseEvent(transPos);
            }
        }
        return ret;
    }

    bool EWAUIWidget::MouseMoveEvent      (const Vec2I & pos)
    {
        bool ret = OnMouseMoveEvent(pos);
        if(ret){
            // 向下传递
            for(int i = 0; i < childWidget.size(); i++) {
                const EyerSmartPtr<EWAUIWidget> & child = childWidget[i];
                Vec2I transPos = pos - (child->xy + offsetXY);
                child->MouseMoveEvent(transPos);
            }
        }
        return ret;
    }

    bool EWAUIWidget::ScrollEvent          (const double x, const double y)
    {
        bool ret = OnScrollEvent(x, y);
        if(ret){
            for(int i = 0; i < childWidget.size(); i++) {
                const EyerSmartPtr<EWAUIWidget> &child = childWidget[i];
                child->ScrollEvent(x, y);
            }
        }
        return ret;
    }

    bool EWAUIWidget::OnMousePressEvent     (const Vec2I & pos)
    {
        return true;
    }

    bool EWAUIWidget::OnMouseReleaseEvent   (const Vec2I & pos)
    {
        return true;
    }

    bool EWAUIWidget::OnMouseMoveEvent      (const Vec2I & pos)
    {
        return true;
    }

    bool EWAUIWidget::OnScrollEvent         (const double x, const double y)
    {
        return true;
    }
}